package com.wugui.datax.admin.tool.generate.dialect;

import cn.hutool.core.util.StrUtil;
import com.wugui.datax.admin.entity.JobDatasource;
import com.wugui.datax.admin.exception.DialectException;
import com.wugui.datax.admin.tool.generate.dialect.helper.*;
import com.wugui.datax.admin.util.JdbcConstants;

import java.util.HashMap;
import java.util.Map;

public class AutoDialect {

    private static Map<String, Class<? extends Dialect>> dialectAliasMap = new HashMap<String, Class<? extends Dialect>>();

    public static void registerDialectAlias(String alias, Class<? extends Dialect> dialectClass) {
        dialectAliasMap.put(alias, dialectClass);
    }

    static {
        registerDialectAlias(JdbcConstants.H2, HsqldbDialect.class);
        registerDialectAlias(JdbcConstants.POSTGRESQL, HsqldbDialect.class);
        registerDialectAlias(JdbcConstants.PHOENIX, HsqldbDialect.class);


        registerDialectAlias(JdbcConstants.MYSQL, MySqlDialect.class);
        registerDialectAlias(JdbcConstants.MARIADB, MySqlDialect.class);
        registerDialectAlias(JdbcConstants.SQLITE, MySqlDialect.class);

        registerDialectAlias(JdbcConstants.ORACLE, OracleDialect.class);
        registerDialectAlias(JdbcConstants.DB2, Db2Dialect.class);

        registerDialectAlias(JdbcConstants.SQL_SERVER, SqlServerDialect.class);

        registerDialectAlias(JdbcConstants.DERBY, SqlServer2012Dialect.class);
        //达梦数据库
        registerDialectAlias(JdbcConstants.DM, OracleDialect.class);
        //阿里云PPAS数据库
        registerDialectAlias(JdbcConstants.ENTERPRISEDB, OracleDialect.class);
    }

    public AutoDialect(JobDatasource jobDataSource) {
        dialectThreadLocal.set(initDialect(jobDataSource.getDatasource()));
    }

    private ThreadLocal<AbstractHelperDialect> dialectThreadLocal = new ThreadLocal<AbstractHelperDialect>();

    //获取当前的代理对象
    public AbstractHelperDialect getDelegate() {
        return dialectThreadLocal.get();
    }

    /**
     * 初始化 helper
     *
     * @param dialectClass
     */
    private AbstractHelperDialect initDialect(String dialectClass) {
        AbstractHelperDialect dialect;
        if (StrUtil.isEmpty(dialectClass)) {
            throw new DialectException("使用 DialectHelper 插件时，必须设置 helper 属性");
        }
        try {
            Class sqlDialectClass = resloveDialectClass(dialectClass);
            if (AbstractHelperDialect.class.isAssignableFrom(sqlDialectClass)) {
                dialect = (AbstractHelperDialect) sqlDialectClass.newInstance();
            } else {
                throw new DialectException("使用 DialectHelper 时，方言必须是实现 " + AbstractHelperDialect.class.getCanonicalName() + " 接口的实现类!");
            }
        } catch (Exception e) {
            throw new DialectException("初始化 helper [" + dialectClass + "]时出错:" + e.getMessage(), e);
        }
        return dialect;
    }


    /**
     * 反射类
     *
     * @param className
     * @return
     * @throws Exception
     */
    private Class resloveDialectClass(String className) throws Exception {
        if (dialectAliasMap.containsKey(className.toLowerCase())) {
            return dialectAliasMap.get(className.toLowerCase());
        } else {
            return Class.forName(className);
        }
    }

}
